package socket_uno;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;

/*
 * O Notificador tem o objetivo de comunicar a todos os clientes (jogadores de uma sala) que existe uma 
 * nova situação (estado) no servidor e que ele precisa requisitar um pedido de atualização ao servidor.
 * 
 * Uma das atualizações é em relação a situação dos jogadores presentes em uma sala.
 * 
 * A medida que um jogador entra ou sai de em uma sala, todos os outros, presentes na sala, deverão 
 * fazer uma requisição de atualização ao servidor, e exibir a nova lista de jogadores presentes 
 * 
 * Forma de funcionamento
 * toda vez que o jogador entrar em uma sala, ele fará uma conexão por socket com o servidor avisando qual
 * nome da sala ele entrou.
 * 
 * */

public class Notificador implements Observer {
	
	private ServerSocket receptor;
	private Map<String, Map<String, Socket>> salas;
	private Socket servidorWebservice;
	
	public Notificador() throws IOException {
		
		receptor = new ServerSocket(2000);
		salas = new HashMap<String, Map<String, Socket>>();
	}
	
	
	private int TIPO_COMANDO = 0;
	private int TIPO_SALA = 1;
	private int TIPO_JOGADOR = 2;
	
	
	@Override
	public void update(Observable o, Object arg) {
		
		String [] argumentos = (String []) arg;
		Map<String, Socket> jogadores = salas.get(argumentos[TIPO_SALA]);
		
		if (argumentos[TIPO_COMANDO].equals("REGISTRAR_CLIENTE")) {
			
			if (jogadores == null) {
				jogadores = new HashMap<String, Socket>();
				jogadores.put(argumentos[TIPO_JOGADOR], ((ThreadFluxoRecebimento) o).getSocket());
				salas.put(argumentos[TIPO_SALA], jogadores);
			} else {
				jogadores.put(argumentos[TIPO_JOGADOR], ((ThreadFluxoRecebimento) o).getSocket());
			}
			
		} else if (argumentos[TIPO_COMANDO].equals("FECHAR_CLIENTE")) {
			
			try {
				jogadores.remove(argumentos[TIPO_JOGADOR]).close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		} else if (argumentos[TIPO_COMANDO].equals("REGISTRAR_SERVIDOR")) {
			
			servidorWebservice = ((ThreadFluxoRecebimento) o).getSocket();
			
		} else if (argumentos[TIPO_COMANDO].equals("NOTIFICAR_CLIENTES")) {
			
			if (jogadores != null) {
				
				for (Socket s: jogadores.values()) {
					new Thread(new ThreadFluxoEnvio(s, "ATUALIZAR")).start();
				}
				
			}
			
		}
		
	}
	
	public static void main(String[] args) {
		
		
		try {
			
			Notificador central = new Notificador();
			
			while (true) {
				
				Socket cliente = central.receptor.accept();
				
				ThreadFluxoRecebimento tIn = new ThreadFluxoRecebimento(cliente);
				tIn.addObserver(central);
				new Thread(tIn).start();
				
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
